<!DOCTYPE html>

<html lang="en">
<head>
  <!-- Required meta tags -->
  <meta charset="utf-8">
  <meta http-equiv="x-ua-compatible" content="ie=edge">
  <meta name="viewport"
        content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
  <meta http-equiv="Content-Security-Policy" content="upgrade-insecure-requests">
  <meta name="baidu-site-verification" content="GOgEP8c1pN"/>
  

  <title>
    Django Pagination 简单分页_Django博客教程_追梦人物的博客</title>

  <link href="font-awesome.min.css"
        rel="stylesheet">
  <link rel="stylesheet" href="mobi.min.css">
  <link rel="stylesheet" href="modal.min.css">
  <link rel="stylesheet" href="friendly.css">
  <link rel="stylesheet" href="blog.css?v0.12">
  <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  <script src="/static/blog/js/menu.js"></script>
  <script src="/static/blog/js/modal.min.js"></script>
  <script src="/static/blog/js/blog.js"></script>
  

  
    <script>
        // baidu statistics
        var _hmt = _hmt || [];
        (function () {
            var hm = document.createElement("script");
            hm.src = "https://hm.baidu.com/hm.js?fb59b2a6022bccc02671a750f61c356b";
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(hm, s);
        })();

        // baidu auto push
        (function () {
            var bp = document.createElement('script');
            var curProtocol = window.location.protocol.split(':')[0];
            if (curProtocol === 'https') {
                bp.src = 'https://zz.bdstatic.com/linksubmit/push.js';
            }
            else {
                bp.src = 'http://push.zhanzhang.baidu.com/push.js';
            }
            var s = document.getElementsByTagName("script")[0];
            s.parentNode.insertBefore(bp, s);
        })();
    </script>
    
  
</head>
<body class="bg-light">
<header>
  <nav class="flex-center bg-white nav-bar">
    <div class="container-wider flex-middle">
      
  <a class="show-on-mobile nav-link m-5" id="js-sidebar-btn" href="#" role="button">
    <i class="fa fa-chevron-right" aria-hidden="true"></i>
  </a>

      <a class="nav-bar-logo mr-7" href="/">
        <img src="/static/blog/images/logo.png" alt="blog logo">
      </a>
      <ul class="unit-0 hide-on-mobile nav-bar-nav">
        <li class="nav-item mr-7">
          <a class="nav-link" href="/">首页</a>
        </li>
        <li class="nav-item mr-7">
          <a class="nav-link" href="/tutorials/">教程</a>
        </li>
        <li class="nav-item mr-7">
          <a class="nav-link" href="/categories/">分类</a>
        </li>
        <li class="nav-item mr-7">
          <a class="nav-link" href="/archives/">归档</a>
        </li>
        <li class="nav-item">
          <a class="nav-link" href="/donate/">赞助</a>
        </li>
      </ul>
      <div class="unit flex-right flex-middle">
        <form class="hide-on-mobile flex-left flex-middle search-form mr-5" id="search-form"
              action="/search/">
          <input class="unit" type="search" name="q" placeholder="搜索..."/>
          <button class="unit-0" type="submit" role="button">
            <i class="fa fa-search" aria-hidden="true"></i>
          </button>
        </form>
        <a class="show-on-mobile nav-link fs-7 mr-7" id="js-search-btn" href="#" role="button">
          <i class="fa fa-search" aria-hidden="true"></i>
        </a>
        <div class="flex-middle notification">
          
            <a class="nav-link" href="/accounts/login/">
              <i class="fa fa-sign-in" aria-hidden="true"></i>
            </a>
          
        </div>
        <div class="show-on-mobile flex-middle">
          <a class="nav-link fs-7 ml-7 mr-5" id="menu-toggle" href="#">
            <i class="fa fa-ellipsis-v" aria-hidden="true"></i>
          </a>
          <ul class="menu bg-white" data-menu data-menu-toggle="#menu-toggle">
            <li class="nav-item mr-7">
              <a class="nav-link" href="/">首页</a>
            </li>
            <li>
              <a href="/tutorials/">教程</a>
            </li>
            <li>
              <a href="/categories/">分类</a>
            </li>
            <li>
              <a href="/archives/">归档</a>
            </li>
            <li>
              <a href="/donate/">赞助</a>
            </li>
          </ul>
        </div>
      </div>
    </div>
  </nav>
</header>
<section class="flex-center">
  <div class="container-wider">
    <!-- 模态框（Modal） -->
    <div class="modal fade" id="myModal" tabindex="-1" role="dialog"
         aria-labelledby="myModalLabel" aria-hidden="true">
      <div class="modal-dialog">
        <div class="modal-content">
          <div class="modal-header">
            <button type="button" class="close" data-dismiss="modal" aria-hidden="true">
              &times;
            </button>
            <h4 class="modal-title" id="myModalLabel">设置评论回复接收邮箱</h4>
            <div class="text-primary mt-2">邮箱仅用于接收回复提醒，不会被公开。</div>
            
          </div>
          <div class="modal-body">
            <form class="form email-binding-form" action="/comments/ajax_email_binding/">
              <div class="message">
                <span class="text-danger"></span>
              </div>
              <input type='hidden' name='csrfmiddlewaretoken' value='XJLvgBt9Y6KPPsCauD8xpxwwlHpmy5u7pLln349Ld4AQBdItnsw2HYs2bGQVGJBG' />
              <div class="flex-left units-gap">
                <label class="unit-0 text-right" for="multiple-inputs-name">邮箱: </label>
                <div class="unit">
                  <input type="email" name="email" id="id_email" placeholder="请输入绑定邮箱"/>
                </div>
                <div class="unit-0">
                  <button class="btn" id="js-send" type="button"
                          data-target="/comments/ajax_verification_code/">发送验证码
                  </button>
                </div>
              </div>
              <div class="flex-left units-gap">
                <label class="unit-0 text-right" for="multiple-inputs-name">验证码: </label>
                <div class="unit">
                  <input type="text" name="verification_code" id="id_verification_code"
                         placeholder="请输入接收到的验证码"/>
                </div>
              </div>
              <div class="flex-right">
                <button type="button" class="btn btn-danger mr-3" data-dismiss="modal">关闭</button>
                <button type="submit" class="btn btn-primary" id="js-submit">设置</button>
              </div>
            </form>
          </div>
        </div><!-- /.modal-content -->
      </div><!-- /.modal -->
    </div>
    <div class="flex-left flex-wrap "
         style="margin-top: 60px">
      
  <aside class="unit-1-4 unit-1-on-mobile top-gap">
    <div class="scroll-view bg-white card toc-sidebar" style="height: 100%">
      <div class="card-header">
        目录
      </div>
      <div class="flex-left">
        <div class="unit-1-4">
          <a href="https://promotion.aliyun.com/ntms/act/group/team.html?group=FcfAncJPAp" target="_blank"><img
              src="/static/blog/images/aliyun.jpg" alt=""></a>
        </div>
        <div class="unit-1-2 flex-vertical top-gap text-small">
          <a style="color: #e83e8c" target="_blank"
             href="https://promotion.aliyun.com/ntms/act/group/team.html?group=FcfAncJPAp">云服务器新用户</a>
          <a style="color: #6610f2" target="_blank"
             href="https://promotion.aliyun.com/ntms/act/group/team.html?group=FcfAncJPAp">8元/月</a>
        </div>
      </div>
      <div class="card-body">
        <ul>
          <li>
            <h6 class="top-gap-0"><a href="">Django博客教程</a></h6>
            <ul>
              
                <li>
                  <a href="2.html">前言</a>
                  
                </li>
              
                <li>
                  <a href="3.html">搭建开发环境</a>
                  
                </li>
              
                <li>
                  <a href="4.html">建立 Django 博客应用</a>
                  
                </li>
              
                <li>
                  <a href="5.html">创建 Django 博客的数据库模型</a>
                  
                </li>
              
                <li>
                  <a href="6.html">让 Django 完成翻译：迁移数据库</a>
                  
                </li>
              
                <li>
                  <a href="7.html">Django 博客首页视图</a>
                  
                </li>
              
                <li>
                  <a href="8.html">真正的 Django 博客首页视图</a>
                  
                </li>
              
                <li>
                  <a href="9.html">在 Django Admin 后台发布文章</a>
                  
                </li>
              
                <li>
                  <a href="10.html">博客文章详情页</a>
                  
                </li>
              
                <li>
                  <a href="11.html">支持 Markdown 语法和代码高亮</a>
                  
                </li>
              
                <li>
                  <a href="12.html">页面侧边栏：使用自定义模板标签</a>
                  
                </li>
              
                <li>
                  <a href="13.html">分类与归档</a>
                  
                </li>
              
                <li>
                  <a href="14.html">评论</a>
                  
                </li>
              
                <li>
                  <a href="16.html">已知小问题修正</a>
                  
                </li>
              
                <li>
                  <a href="20.html">使用 Nginx 和 Gunicorn 部署 Django 博客</a>
                  
                </li>
              
                <li>
                  <a href="21.html">使用 Fabric 自动化部署</a>
                  
                </li>
              
                <li>
                  <a href="29.html">统计文章阅读量</a>
                  
                </li>
              
                <li>
                  <a href="32.html">自动生成文章摘要</a>
                  
                </li>
              
                <li>
                  <a href="33.html">基于类的通用视图：ListView 和 DetailView</a>
                  
                </li>
              
                <li>
                  <a href="34.html">Django Pagination 简单分页</a>
                  
                    <div class="toc">
<ul>
<li><a href="#paginator-类的常用方法">Paginator 类的常用方法</a></li>
<li><a href="#用-paginator-给文章列表分页">用 Paginator 给文章列表分页</a></li>
<li><a href="#在模板中设置分页导航">在模板中设置分页导航</a></li>
<li><a href="#进一步拓展">进一步拓展</a></li>
<li><a href="#总结">总结</a></li>
</ul>
</div>

                  
                </li>
              
                <li>
                  <a href="37.html">Django Pagination 完善分页</a>
                  
                </li>
              
                <li>
                  <a href="38.html">统计各个分类下的文章数</a>
                  
                </li>
              
                <li>
                  <a href="39.html">标签云</a>
                  
                </li>
              
                <li>
                  <a href="41.html">RSS 订阅</a>
                  
                </li>
              
                <li>
                  <a href="43.html">Markdown 自动生成文章目录</a>
                  
                </li>
              
                <li>
                  <a href="44.html">简单全文搜索</a>
                  
                </li>
              
                <li>
                  <a href="45.html">Django Haystack 全文检索与关键词高亮</a>
                  
                </li>
              
            </ul>
          </li>
        </ul>
      </div>
    </div>
  </aside>

      
  <div class="unit-3-4 unit-1-on-mobile top-gap">
    


<div class="bg-white card post-card px-7 py-5">
  
<article class="post">
  <h1 class="top-gap-0">Django Pagination 简单分页</h1>
  <ul class="list-inline dot-divider post-meta">
    <li class="list-inline-item text-small text-muted">
      10 月，2 周前
    </li>
    <li class="list-inline-item text-small text-muted">3788 字
    </li>
    <li class="list-inline-item text-small text-muted">
      10440 阅读
    </li>
    <li class="list-inline-item text-small text-muted">
      14 评论
    </li>
  </ul>
  <div class="top-gap-big post-body">
    <p>当博客上发布的文章越来越多时，通常需要进行分页显示，以免所有的文章都堆积在一个页面，影响用户体验。Django 内置的 Pagination 能够帮助我们实现简单的分页功能。</p>
<h2 id="paginator-类的常用方法">Paginator 类的常用方法</h2>
<p>分页功能由 Django 内置的 <code>Paginator</code> 类提供。这个类位于 django/core/paginator.py，需要使用它时，只需在适当的地方导入这个类即可。下面的代码摘自 Django 的官方文档中 <a href="https://docs.djangoproject.com/en/1.10/topics/pagination/">Pagination</a> 的示例。</p>
<div class="codehilite"><pre><span></span><span class="kn">from</span> <span class="nn">django.core.paginator</span> <span class="kn">import</span> <span class="n">Paginator</span>
</pre></div>


<p>只需实例化一个 <code>Paginator</code> 对象，并在实例化时传入一个需要分页的列表对象，就可以得到分页后的对象数据。</p>
<div class="codehilite"><pre><span></span><span class="c1"># 对 item_list 进行分页，每页包含 2 个数据。</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">item_list</span> <span class="o">=</span> <span class="p">[</span><span class="s1">&#39;john&#39;</span><span class="p">,</span> <span class="s1">&#39;paul&#39;</span><span class="p">,</span> <span class="s1">&#39;george&#39;</span><span class="p">,</span> <span class="s1">&#39;ringo&#39;</span><span class="p">]</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">p</span> <span class="o">=</span> <span class="n">Paginator</span><span class="p">(</span><span class="n">item_list</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
</pre></div>


<p>取特定页的数据：</p>
<div class="codehilite"><pre><span></span><span class="c1"># 取第 2 页的数据</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">page2</span> <span class="o">=</span> <span class="n">p</span><span class="o">.</span><span class="n">page</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">page2</span><span class="o">.</span><span class="n">object_list</span>
<span class="p">[</span><span class="s1">&#39;george&#39;</span><span class="p">,</span> <span class="s1">&#39;ringo&#39;</span><span class="p">]</span>
</pre></div>


<p>查询特定页的当前页码数：</p>
<div class="codehilite"><pre><span></span><span class="o">&gt;&gt;&gt;</span> <span class="n">page2</span><span class="o">.</span><span class="n">number</span>
<span class="mi">2</span>
</pre></div>


<p>查看分页后的总页数：</p>
<div class="codehilite"><pre><span></span><span class="o">&gt;&gt;&gt;</span> <span class="n">p</span><span class="o">.</span><span class="n">num_pages</span>
<span class="mi">2</span>
</pre></div>


<p>查看某一页是否还有上一页，以及查询该页上一页的页码：</p>
<div class="codehilite"><pre><span></span><span class="c1"># 查询第二页是否还有上一页</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">page2</span><span class="o">.</span><span class="n">has_previous</span><span class="p">()</span>
<span class="bp">True</span>

<span class="c1"># 查询第二页上一页的页码</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">page2</span><span class="o">.</span><span class="n">previous_page_number</span><span class="p">()</span>
<span class="mi">1</span>
</pre></div>


<p>查看某一页是否还有下一页，以及查询该页下一页的页码：</p>
<div class="codehilite"><pre><span></span><span class="c1"># 查询第二页是否还有下一页</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">page2</span><span class="o">.</span><span class="n">has_next</span><span class="p">()</span>
<span class="bp">False</span>

<span class="c1"># 查询第二页下一页的页码</span>
<span class="o">&gt;&gt;&gt;</span> <span class="n">page2</span><span class="o">.</span><span class="n">next_page_number</span><span class="p">()</span>
<span class="n">django</span><span class="o">.</span><span class="n">core</span><span class="o">.</span><span class="n">paginator</span><span class="o">.</span><span class="n">EmptyPage</span><span class="p">:</span> <span class="n">That</span> <span class="n">page</span> <span class="n">contains</span> <span class="n">no</span> <span class="n">results</span>
</pre></div>


<p>更多方法和属性请参阅 <a href="https://docs.djangoproject.com/en/1.10/topics/pagination/">Django Pagination 的官方文档</a>。</p>
<h2 id="用-paginator-给文章列表分页">用 Paginator 给文章列表分页</h2>
<p>使用上面的一些方法，我们可以实现一个类似于 Django 官方博客一样的简单分页效果，效果如下。</p>
<p><img alt="Django官方博客简单分页效果" src="//bkt.zmrenwu.com/Django%E5%AE%98%E6%96%B9%E5%8D%9A%E5%AE%A2%E7%AE%80%E5%8D%95%E5%88%86%E9%A1%B5%E6%95%88%E6%9E%9C.png" /></p>
<p>这里，Django 的官方文档中给出了一个在视图函数中对列表进行分页的示例，这个视图函数获取一个联系人列表并对其分页：</p>
<div class="codehilite"><pre><span></span><span class="kn">from</span> <span class="nn">django.core.paginator</span> <span class="kn">import</span> <span class="n">Paginator</span><span class="p">,</span> <span class="n">EmptyPage</span><span class="p">,</span> <span class="n">PageNotAnInteger</span>
<span class="kn">from</span> <span class="nn">django.shortcuts</span> <span class="kn">import</span> <span class="n">render</span>

<span class="k">def</span> <span class="nf">listing</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
    <span class="n">contact_list</span> <span class="o">=</span> <span class="n">Contacts</span><span class="o">.</span><span class="n">objects</span><span class="o">.</span><span class="n">all</span><span class="p">()</span>
    <span class="n">paginator</span> <span class="o">=</span> <span class="n">Paginator</span><span class="p">(</span><span class="n">contact_list</span><span class="p">,</span> <span class="mi">25</span><span class="p">)</span> <span class="c1"># 每页显示 25 个联系人</span>

    <span class="n">page</span> <span class="o">=</span> <span class="n">request</span><span class="o">.</span><span class="n">GET</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">&#39;page&#39;</span><span class="p">)</span>
    <span class="k">try</span><span class="p">:</span>
        <span class="n">contacts</span> <span class="o">=</span> <span class="n">paginator</span><span class="o">.</span><span class="n">page</span><span class="p">(</span><span class="n">page</span><span class="p">)</span>
    <span class="k">except</span> <span class="n">PageNotAnInteger</span><span class="p">:</span>
        <span class="c1"># 如果用户请求的页码号不是整数，显示第一页</span>
        <span class="n">contacts</span> <span class="o">=</span> <span class="n">paginator</span><span class="o">.</span><span class="n">page</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
    <span class="k">except</span> <span class="n">EmptyPage</span><span class="p">:</span>
        <span class="c1"># 如果用户请求的页码号超过了最大页码号，显示最后一页</span>
        <span class="n">contacts</span> <span class="o">=</span> <span class="n">paginator</span><span class="o">.</span><span class="n">page</span><span class="p">(</span><span class="n">paginator</span><span class="o">.</span><span class="n">num_pages</span><span class="p">)</span>

    <span class="k">return</span> <span class="n">render</span><span class="p">(</span><span class="n">request</span><span class="p">,</span> <span class="s1">&#39;list.html&#39;</span><span class="p">,</span> <span class="p">{</span><span class="s1">&#39;contacts&#39;</span><span class="p">:</span> <span class="n">contacts</span><span class="p">})</span>
</pre></div>


<p>这就是在视图函数中使用分页的代码逻辑，你可以把它当做一个模板应用于自己的任何需要分页的视图函数。不过在我们的博客项目中，我们不必写这些代码了。回顾在 <a href="">基于类的通用视图：ListView 和 DetailView</a> 中的内容，我们已将视图函数转换成了类视图。而类视图 <code>ListView</code> 已经帮我们写好了上述的分页逻辑，我们只需通过指定 <code>paginate_by</code> 属性来开启分页功能即可，即在类视图中指定 <code>paginate_by</code>  属性的值：</p>
<div class="codehilite"><pre><span></span><span class="n">blog</span><span class="o">/</span><span class="n">views</span><span class="o">.</span><span class="n">py</span>

<span class="k">class</span> <span class="nc">IndexView</span><span class="p">(</span><span class="n">ListView</span><span class="p">):</span>
    <span class="n">model</span> <span class="o">=</span> <span class="n">Post</span>
    <span class="n">template_name</span> <span class="o">=</span> <span class="s1">&#39;blog/index.html&#39;</span>
    <span class="n">context_object_name</span> <span class="o">=</span> <span class="s1">&#39;post_list&#39;</span>
    <span class="c1"># 指定 paginate_by 属性后开启分页功能，其值代表每一页包含多少篇文章</span>
    <span class="n">paginate_by</span> <span class="o">=</span> <span class="mi">10</span>
</pre></div>


<p>这里我们设置了每 10 篇文章一页，当然你的测试数据可能不够。为了看到分页效果，你可以把这个数值减小。这样首页的文章列表就已经分好页了。</p>
<h2 id="在模板中设置分页导航">在模板中设置分页导航</h2>
<p>接下来便是在模板中设置分页导航，比如上一页、下一页的按钮，以及显示一些页面信息。我们这里设置和 Django 官方博客那样的分页导航样式（具体的样式见上图）。<code>ListView</code> 传递了以下和分页有关的模板变量供我们在模板中使用：</p>
<ul>
<li><code>paginator</code> ，即 <code>Paginator</code> 的实例。</li>
<li><code>page_obj</code> ，当前请求页面分页对象。</li>
<li><code>is_paginated</code>，是否已分页。只有当分页后页面超过两页时才算已分页。</li>
<li><code>object_list</code>，请求页面的对象列表，和 <code>post_list</code> 等价。所以在模板中循环文章列表时可以选 <code>post_list</code> ，也可以选 <code>object_list</code>。</li>
</ul>
<p>模板中使用示例：</p>
<div class="codehilite"><pre><span></span>templates/blog/index.html

{% if is_paginated %}
<span class="p">&lt;</span><span class="nt">div</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;pagination-simple&quot;</span><span class="p">&gt;</span>
  <span class="c">&lt;!-- 如果当前页还有上一页，显示一个上一页的按钮 --&gt;</span>
  {% if page_obj.has_previous %}
    <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;?page={{ page_obj.previous_page_number }}&quot;</span><span class="p">&gt;</span>上一页<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
  {% endif %}
  <span class="c">&lt;!-- 显示当前页面信息 --&gt;</span>
  <span class="p">&lt;</span><span class="nt">span</span> <span class="na">class</span><span class="o">=</span><span class="s">&quot;current&quot;</span><span class="p">&gt;</span>第 {{ page_obj.number }} 页 / 共 {{ paginator.num_pages }} 页<span class="p">&lt;/</span><span class="nt">span</span><span class="p">&gt;</span>
  <span class="c">&lt;!-- 如果当前页还有下一页，显示一个下一页的按钮 --&gt;</span>
  {% if page_obj.has_next %}
    <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&quot;?page={{ page_obj.next_page_number }}&quot;</span><span class="p">&gt;</span>下一页<span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
  {% endif %}
<span class="p">&lt;/</span><span class="nt">div</span><span class="p">&gt;</span>
{% endif %}
</pre></div>


<p>其中 {{ }} 模板变量中的内容，其含义已在文章开头部分的<strong>Paginator 类的常用方法</strong>中已有介绍。最终我们得到如下的分页效果：</p>
<p><img alt="Django 简单分页效果" src="//bkt.zmrenwu.com/Django%20%E7%AE%80%E5%8D%95%E5%88%86%E9%A1%B5%E6%95%88%E6%9E%9C.png" /></p>
<p>当然这只是一个简单示例，分页导航处的视觉效果并不是很好看，你可以自行为其添加 CSS 样式使其看上去更加美观。</p>
<h2 id="进一步拓展">进一步拓展</h2>
<p>使用 Django 内置的 Pagination 只能实现上面的简单分页效果，但通常更加高级的分页效果应该像下图这样：</p>
<p><img alt="高级分页效果图" src="//bkt.zmrenwu.com/%E9%AB%98%E7%BA%A7%E5%88%86%E9%A1%B5%E6%95%88%E6%9E%9C.png" /></p>
<p>当前页面高亮显示，且显示当前页面前后几页的页码，始终显示第一页和最后一页的页码，中间可能还有省略号的效果，表示还有未显示的页码。</p>
<p>仅仅使用 Django Pagination 内置的方法无法实现这样的效果，需要我们写一些额外的代码来拓展 Pagination 的功能。接下来我们将详细说明该如何拓展 Pagination 以实现一个完善的分页效果。</p>
<h2 id="总结">总结</h2>
<p>本章节的代码位于：<a href="https://github.com/zmrenwu/django-blog-tutorial/tree/Step19_simple-pagination">Step19: simple pagination</a>。</p>
<p>如果遇到问题，请通过下面的方式寻求帮助。</p>
<ul>
<li>在下方评论区留言。</li>
<li>将问题的详细描述通过邮件发送到 djangostudyteam@163.com，一般会在 24 小时内回复。</li>
<li>在 <a href="http://www.pythonzh.cn/category/newbie-qa/">Pythonzhcn 社区的新手问答版块</a> 发布帖子。</li>
</ul>
    <p class="text-center">
      -- EOF --
    </p>
    <div>
      <button class="btn btn-primary" id="js-reward"><i class="fa fa-jpy"
                                                        aria-hidden="true"></i>
        如果觉得文章对你有帮助，请随意打赏
        <i class="fa fa-chevron-down" aria-hidden="true"></i>
      </button>
      <div class="flex-left flex-wrap units-gap-big mt-4" style="display: none">
        <div class="unit unit-1-on-mobile flex-center">
          <figure>
            <img src="/static/blog/images/weixinpay.jpg" alt="微信支付收款二维码"
                 style="width: 250px">
            <figcaption class="text-center fs-6 mt-2" style="color: green">微信</figcaption>
          </figure>
        </div>
        <div class="unit unit-1-on-mobile flex-center">
          <figure>
            <img src="/static/blog/images/alipay.jpg" alt="支付宝收款二维码" style="width: 250px">
            <figcaption class="text-center fs-6 mt-2 text-primary">支付宝</figcaption>
          </figure>
        </div>
      </div>
    </div>
    <div class="post-tags">
      <ul class="list-inline">
        
      </ul>
    </div>
  </div>
</article>
  <div class="top-gap">
    <div class="jiathis_style">
      <span class="jiathis_txt">分享到：</span>
      <a class="jiathis_button_qzone">QQ空间</a>
      <a class="jiathis_button_tsina">新浪微博</a>
      <a class="jiathis_button_tqq">腾讯微博</a>
      <a class="jiathis_button_weixin">微信</a>
      <a href="http://www.jiathis.com/share?uid=2128865"
         class="jiathis jiathis_txt jiathis_separator jtico jtico_jiathis"
         target="_blank">更多</a>
      <a class="jiathis_counter_style"></a>
    </div>
    <script type="text/javascript">
        var jiathis_config = {data_track_clickback: 'true'};
    </script>
    <script type="text/javascript" src="http://v3.jiathis.com/code/jia.js?uid=2128865"
            charset="utf-8"></script>
    <!-- JiaThis Button END -->
  </div>
  <br>
  <div class="top-gap clearfix">
    
      <a href="33.html">
        <i class="fa fa-angle-double-left" aria-hidden="true"></i>
        基于类的通用视图：ListView 和 DetailView
      </a>
    
    
      <a class="float-right" href="37.html">
        Django Pagination 完善分页
        <i class="fa fa-angle-double-right" aria-hidden="true"></i>
      </a>
    
  </div>
  

  <section class="comment-area top-gap-big" id="comment-area">
    <h5>14 条评论 / 7 人参与</h5>
    
      
<div class="flex-center top-gap login-panel p-7">
  <div>
    <div class="text-muted text-center login-header"><span>登录后回复</span></div>
    <div class="flex-center text-center social-icons mt-3">
                        <span class="weibo mr-3">
                            <a href="/accounts/weibo/login/">
                                <i class="fa fa-weibo" aria-hidden="true"></i>
                            </a>
                        </span>
      <span class="github">
                            <a href="/accounts/github/login/">
                                <i class="fa fa-github" aria-hidden="true"></i>
                            </a>
                        </span>
    </div>
  </div>
</div>
    
    <div class="top-gap-big comment-list">
  
    <div class="flex-left py-4" id="c2046">
      <div class="unit-0">
        <img class="comment-avatar mr-3" src="https://avatars0.githubusercontent.com/u/33800727?v=4"/>
      </div>
      <div class="unit">
        <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">彭志鹏
          
        </span>
    
  </header>
  <div class="comment-body">
    <p>尝试了下不用类视图做的</p><p>```views.py</p><p>def index(request):&nbsp;</p><p>post_list=Post.objects.all()&nbsp;</p><p>paginator=Paginator(post_list,5)&nbsp;</p><p>page=request.GET.get('page')&nbsp;</p><p>try: contacts=paginator.page(page)&nbsp;</p><p>except PageNotAnInteger: contacts=paginator.page(1)&nbsp;</p><p>except EmptyPage: contacts=paginator.page(paginator.num_pages)&nbsp;</p><p>return render(request,'blog/index.html',context={'contacts':contacts})</p><p>```</p><p>```index.html</p><p>div class="pagination-simple"&gt;&nbsp;</p><p>&nbsp;{% if contacts.has_previous %}&nbsp;</p><p>&nbsp;&lt;a href="?page={{contacts.previous_page_number }}"&gt;上一页&lt;/a&gt;&nbsp;</p><p>&nbsp;{% endif %}&nbsp;</p><p>&nbsp;&lt;span class="current"&gt;第{{ contacts.number }}页/共{{ contacts.paginator.num_pages }}页&lt;/span&gt;&nbsp;</p><p>&nbsp;{% if contacts.has_next %}    &lt;a href="?page={{ contacts.next_page_number }}"&gt;下一页&lt;/a&gt;&nbsp;</p><p>&nbsp;{% endif %}</p><p>&nbsp;&lt;/div&gt;<br></p><p>```</p>
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">3 月，2 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/2046"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>
        
        <div class="comment-descendant-list">
          
        </div>
      </div>
    </div>
    
      <hr class="m-0">
    
  
    <div class="flex-left py-4" id="c1444">
      <div class="unit-0">
        <img class="comment-avatar mr-3" src="https://avatars1.githubusercontent.com/u/17778173?v=4"/>
      </div>
      <div class="unit">
        <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">Alan
          
        </span>
    
  </header>
  <div class="comment-body">
    <p>怎么弄都没有分页的效果，不知道错在哪里了<br><br></p>
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">6 月，3 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/1444"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>
        
          <hr class="">
        
        <div class="comment-descendant-list">
          
            <div class="flex-left py-4" id="c1445">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars1.githubusercontent.com/u/17778173?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">Alan
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">Alan
        

  </header>
  <div class="comment-body">
    <p>好了，是我的nginx代理有问题</p>
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">6 月，3 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/1445"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
          
        </div>
      </div>
    </div>
    
      <hr class="m-0">
    
  
    <div class="flex-left py-4" id="c417">
      <div class="unit-0">
        <img class="comment-avatar mr-3" src="https://avatars1.githubusercontent.com/u/19534921?v=4"/>
      </div>
      <div class="unit">
        <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">DawnOct
          
        </span>
    
  </header>
  <div class="comment-body">
    这相当于是,提前将所有的数据加载进内存了.  没有达到分页加载数据啊..
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">9 月，3 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/417"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>
        
          <hr class="">
        
        <div class="comment-descendant-list">
          
            <div class="flex-left py-4" id="c418">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars2.githubusercontent.com/u/13174219?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">追梦人物
          
            <span class="master">[博主]</span>
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">DawnOct
        

  </header>
  <div class="comment-body">
    为什么呢？
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">9 月，3 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/418"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
              <hr class="m-0">
            
          
            <div class="flex-left py-4" id="c419">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars1.githubusercontent.com/u/19534921?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">DawnOct
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">追梦人物
        
            <span class="master">[博主]</span>
        

  </header>
  <div class="comment-body">
    我的意思是,  比如数据库里有1000条数据, 通过contact_list = Contacts.objects.all()将1000条数据读取出来了, 然后只是在页面展示的时候,做了分页. 这样的话,如果数据库有一百万条, 而用户只需要看前两条的页面,这样是不是体验会不太好?    我对分页的理解是, 用户点击了第二页,再去数据库读取第二页数据.
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">9 月，3 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/419"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
              <hr class="m-0">
            
          
            <div class="flex-left py-4" id="c420">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars2.githubusercontent.com/u/13174219?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">追梦人物
          
            <span class="master">[博主]</span>
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">DawnOct
        

  </header>
  <div class="comment-body">
    Contacts.objects.all() 在没有被 evaluated（求值？） 时，是没有 hit 数据库的。虽然我没有看过 Pagination 的源码，但我猜测在内部实现中肯定用了数据库的 offset，这样真正从数据库取的数据就是用户请求的那一页的数据。
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">9 月，3 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/420"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
              <hr class="m-0">
            
          
            <div class="flex-left py-4" id="c421">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars1.githubusercontent.com/u/19534921?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">DawnOct
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">追梦人物
        
            <span class="master">[博主]</span>
        

  </header>
  <div class="comment-body">
    神奇~~~ 感谢楼主...  期待楼主有机会讲解一下django rest framework
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">9 月，3 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/421"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
              <hr class="m-0">
            
          
            <div class="flex-left py-4" id="c423">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars2.githubusercontent.com/u/13174219?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">追梦人物
          
            <span class="master">[博主]</span>
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">DawnOct
        

  </header>
  <div class="comment-body">
    那个我就没用过了，目前还没碰到类似需求。
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">9 月，3 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/423"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
              <hr class="m-0">
            
          
            <div class="flex-left py-4" id="c2131">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars1.githubusercontent.com/u/9687187?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">rsd
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">追梦人物
        
            <span class="master">[博主]</span>
        

  </header>
  <div class="comment-body">
    <p>context.get("paginator")打印了一下paginator.__dict__，它竟然查的全部。。。<br></p>
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">2 月，4 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/2131"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
          
        </div>
      </div>
    </div>
    
      <hr class="m-0">
    
  
    <div class="flex-left py-4" id="c184">
      <div class="unit-0">
        <img class="comment-avatar mr-3" src="https://avatars2.githubusercontent.com/u/4308045?v=3"/>
      </div>
      <div class="unit">
        <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">dengwen168
          
        </span>
    
  </header>
  <div class="comment-body">
    博主，您好，看你的教程设置数据库的时候设置了一个tag字段，请问一下下次能不能写个教程介绍一下，如何像其他cms那样，在一个区块显示所有的tags？谢谢！
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">10 月，2 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/184"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>
        
          <hr class="">
        
        <div class="comment-descendant-list">
          
            <div class="flex-left py-4" id="c188">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars2.githubusercontent.com/u/13174219?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">追梦人物
          
            <span class="master">[博主]</span>
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">dengwen168
        

  </header>
  <div class="comment-body">
    嗯，相关教程正在撰写中。
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">10 月，2 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/188"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
          
        </div>
      </div>
    </div>
    
      <hr class="m-0">
    
  
    <div class="flex-left py-4" id="c172">
      <div class="unit-0">
        <img class="comment-avatar mr-3" src="https://avatars3.githubusercontent.com/u/20854296?v=4"/>
      </div>
      <div class="unit">
        <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">kuaidanian
          
        </span>
    
  </header>
  <div class="comment-body">
    感谢，正在学习博主的教程，受益颇多，准备就以博主的教程搭建自己的博客，希望博主以后能多写一些教程，支持博主。
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">10 月，2 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/172"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>
        
          <hr class="">
        
        <div class="comment-descendant-list">
          
            <div class="flex-left py-4" id="c173">
              <div class="unit-0">
                <img class="comment-avatar mr-3" src="https://avatars2.githubusercontent.com/u/13174219?v=4"/>
              </div>
              <div class="unit">
                
  <div class="comment-main">
  <header class="comment-user">
        <span class="text-small text-muted nickname">追梦人物
          
            <span class="master">[博主]</span>
          
        </span>
    
    <span class="reply-label text-small text-muted">
                                                        <i class="fa fa-share" aria-hidden="true"></i>
                                                    </span>
    <span class="nickname text-small text-muted">kuaidanian
        

  </header>
  <div class="comment-body">
    感谢支持，会一直写的。
  </div>
  <footer class="comment-footer flex-left">
    <ul class="unit list-inline dot-divider">
      <li class="list-inline-item">
        <time class="text-small text-muted">10 月，2 周前</time>
      </li>
      <li class="list-inline-item">
        <a href="/comments/reply/173"
           class="reply-btn text-small text-muted">回复</a>
      </li>
    </ul>
  </footer>
</div>

              </div>
            </div>
            
          
        </div>
      </div>
    </div>
    
  
</div>
  </section>
</div>
  </div>

    </div>
  </div>
</section>
<footer class="bg-white py-5 mt-5 text-small text-muted">
  <div class="flex-center">
    <div>&copy; 2017 追梦人物的博客</div>
  </div>
  
  
  
</footer>
<script>
    $('[data-menu]').menu();

    var InterValObj; //timer变量，控制时间
    var curCount = 120;//当前剩余秒数

    $('#js-send').on('click', function (event) {
        var $this = $(this);
        var $targetURL = $this.attr('data-target');
        $.post(
            $targetURL,
            {email: $('#id_email').val()},
            function (data) {
                if (data.ok) {
                    $this.attr("disabled", "true");
                    $this.text("重新发送验证码" + "(" + curCount + ")");
                    InterValObj = window.setInterval(SetRemainTime, 1000); //启动计时器，1秒执行一次
                    $('.message')
                        .find('span')
                        .text(data.msg)
                } else {
                    $('.message').find('span').text(data.msg)
                }
            }
        );
        return false;
    });

    //timer处理函数
    function SetRemainTime() {
        if (curCount === 0) {
            window.clearInterval(InterValObj);//停止计时器
            $('#js-send').removeAttr("disabled");//启用按钮
            $('#js-send').text("重新发送验证码");
        }
        else {
            curCount--;
            $('#js-send').text("重新发送验证码" + "(" + curCount + ")");
        }
    }

    $('#js-submit').on('click', function (event) {
        var $this = $(this);
        var $form = $('.email-binding-form');
        var $targetURL = $form.attr('action');
        console.log($targetURL);

        $.post(
            $targetURL,
            {
                email: $('#id_email').val(),
                verification_code: $('#id_verification_code').val()
            },
            function (data) {
                if (data.ok) {
                    location.reload();
                } else {
                    $('.message')
                        .find('span')
                        .text(data.msg)
                }
            }
        );
        return false;
    });


    var editor = new Simditor({
        textarea: $('#id_comment'),
        placeholder: "提出你的见解...",
        toolbarFloat: false,
        cleanPaste: true,
        toolbar: [
            'bold',
            'italic',
            'underline',
            'strikethrough',
            'color',
            'ol',
            'ul',
            'blockquote',
            'code',
            'table',
            'link',
            'image',
            'hr'
        ]
    });
</script>


</body>
</html>